﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;

namespace CodeGenerator.CSharp
{
    public class Body
    {
        #region Constructors
        
        internal Body(CodeUnit parent)
        { 
            this._parentCodeUnit = parent; 
        }
        private CodeUnit _parentCodeUnit;
        private List<IBodyItem> _bodyItems = new List<IBodyItem>();

        #endregion

        #region ToString

        public override string ToString()
        {
            CodeBuilder Code = new CodeBuilder();
            int IndentationLevel = this._parentCodeUnit.IndentationLevel + (this._parentCodeUnit is Property ? 2 : 1);
            string Padding = new String(' ', IndentationLevel * Settings.CharactersPerTab);
			foreach (IBodyItem ThisItem in this._bodyItems)
				Code.Add(ThisItem.ToString(Padding));

            //Remove any extra carriage returns.
            if (Code.Length > 2) Code.Remove(Code.Length - 2, 2);
            return Code.ToString();
        }

        #endregion

        #region Add

        /// <summary>
		/// Adds a line of code to this body.
		/// </summary>
		public void Add(string text) 
        { 
            this._bodyItems.Add(new LineOfCode(text)); 
        }

        /// <summary>
        /// Adds a formatted line of code to this body.
        /// </summary>
        public void Add(string format, params object[] args)
        {
            this.Add(string.Format(format, args));
        }

        /// <summary>
        /// Adds a comment to this body.
        /// </summary>
        public void AddComment(string text) 
        { 
            this._bodyItems.Add(new Comment(text)); 
        }

        /// <summary>
        /// Adds a blank line to this body.
        /// </summary>
        public void AddBlankLine() 
        { 
            this._bodyItems.Add(BlankLine.Instance()); 
        } 

        #endregion

        #region Classes & Interfaces

        /// <summary>
        /// Interface into the body items.
        /// </summary>
        internal interface IBodyItem
        { string ToString(string padding); }

		///// <summary>
		///// Represents a single line of code.
		///// </summary>
		//internal class LineOfCode : IBodyItem
		//{
		//    public LineOfCode(string text, Language.Name languageName) 
		//    {
		//        this.Text = text;
		//        this.LanguageName = languageName; 
		//    }

		//    public string Text { get; set; }
		//    public Language.Name LanguageName { get; set; }
		//    public bool IsVB { get { return this.LanguageName == Language.Name.VB; } }
		//    public bool IsCSharp { get { return this.LanguageName == Language.Name.CSharp; } }
		//    public string ToString(string padding)
		//    { return padding + this.Text; }
		//}

		/// <summary>
		/// Represents a single line of code.
		/// </summary>
		internal class LineOfCode : IBodyItem
		{
			public LineOfCode(string text) { this.Text = text; }
			public string Text { get; set; }
			public string ToString(string padding) { return padding + this.Text; }
		}

        /// <summary>
        /// Defines a comment body item.
        /// </summary>
        internal class Comment : IBodyItem
        {
            public Comment(string text) { this.Text = text; }
            public string Text { get; set; }
            public string ToString(string padding)
            {
				padding += "// ";
                return Utilities.ParseText(this.Text, padding);
            }
        }

        /// <summary>
        /// Defines a blank line.
        /// </summary>
        internal class BlankLine : IBodyItem
        {
            private BlankLine() { }
            public static BlankLine Instance() { return _Instance; }
            private static BlankLine _Instance = new BlankLine();
            public string ToString(string padding) { return padding; }
        }


        #endregion
    }


}
